﻿namespace UnityEngine
{
    using System;
    using System.Runtime.CompilerServices;

    public sealed class Texture2D : Texture
    {
        public Texture2D(int width, int height)
        {
            Internal_Create(this, width, height, TextureFormat.ARGB32, true, false);
        }

        public Texture2D(int width, int height, TextureFormat format, bool mipmap)
        {
            Internal_Create(this, width, height, format, mipmap, false);
        }

        public Texture2D(int width, int height, TextureFormat format, bool mipmap, bool linear)
        {
            Internal_Create(this, width, height, format, mipmap, linear);
        }

        public void Apply()
        {
            bool makeNoLongerReadable = false;
            bool updateMipmaps = true;
            this.Apply(updateMipmaps, makeNoLongerReadable);
        }

        public void Apply(bool updateMipmaps)
        {
            bool makeNoLongerReadable = false;
            this.Apply(updateMipmaps, makeNoLongerReadable);
        }

        [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall]
        public extern void Apply(bool updateMipmaps, bool makeNoLongerReadable);
        public void Compress(bool highQuality)
        {
            INTERNAL_CALL_Compress(this, highQuality);
        }

        [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall]
        public extern byte[] EncodeToPNG();
        [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall]
        public extern Color GetPixel(int x, int y);
        [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall]
        public extern Color GetPixelBilinear(float u, float v);
        public Color[] GetPixels()
        {
            int miplevel = 0;
            return this.GetPixels(miplevel);
        }

        public Color[] GetPixels(int miplevel)
        {
            int blockWidth = this.width >> miplevel;
            if (blockWidth < 1)
            {
                blockWidth = 1;
            }
            int blockHeight = this.height >> miplevel;
            if (blockHeight < 1)
            {
                blockHeight = 1;
            }
            return this.GetPixels(0, 0, blockWidth, blockHeight, miplevel);
        }

        public Color[] GetPixels(int x, int y, int blockWidth, int blockHeight)
        {
            int miplevel = 0;
            return this.GetPixels(x, y, blockWidth, blockHeight, miplevel);
        }

        [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall]
        public extern Color[] GetPixels(int x, int y, int blockWidth, int blockHeight, int miplevel);
        public Color32[] GetPixels32()
        {
            int miplevel = 0;
            return this.GetPixels32(miplevel);
        }

        [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall]
        public extern Color32[] GetPixels32(int miplevel);
        [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall]
        private static extern void INTERNAL_CALL_Compress(Texture2D self, bool highQuality);
        [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall]
        private static extern void INTERNAL_CALL_ReadPixels(Texture2D self, ref Rect source, int destX, int destY, bool recalculateMipMaps);
        [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall]
        private static extern void INTERNAL_CALL_SetPixel(Texture2D self, int x, int y, ref Color color);
        [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall]
        private static extern void Internal_Create([Writable] Texture2D mono, int width, int height, TextureFormat format, bool mipmap, bool linear);
        [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall]
        private extern bool Internal_ResizeWH(int width, int height);
        [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall]
        public extern bool LoadImage(byte[] data);
        public Rect[] PackTextures(Texture2D[] textures, int padding)
        {
            bool makeNoLongerReadable = false;
            int maximumAtlasSize = 0x800;
            return this.PackTextures(textures, padding, maximumAtlasSize, makeNoLongerReadable);
        }

        public Rect[] PackTextures(Texture2D[] textures, int padding, int maximumAtlasSize)
        {
            bool makeNoLongerReadable = false;
            return this.PackTextures(textures, padding, maximumAtlasSize, makeNoLongerReadable);
        }

        [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall]
        public extern Rect[] PackTextures(Texture2D[] textures, int padding, int maximumAtlasSize, bool makeNoLongerReadable);
        public void ReadPixels(Rect source, int destX, int destY)
        {
            bool recalculateMipMaps = true;
            INTERNAL_CALL_ReadPixels(this, ref source, destX, destY, recalculateMipMaps);
        }

        public void ReadPixels(Rect source, int destX, int destY, bool recalculateMipMaps)
        {
            INTERNAL_CALL_ReadPixels(this, ref source, destX, destY, recalculateMipMaps);
        }

        public bool Resize(int width, int height)
        {
            return this.Internal_ResizeWH(width, height);
        }

        [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall]
        public extern bool Resize(int width, int height, TextureFormat format, bool hasMipMap);
        public void SetPixel(int x, int y, Color color)
        {
            INTERNAL_CALL_SetPixel(this, x, y, ref color);
        }

        public void SetPixels(Color[] colors)
        {
            int miplevel = 0;
            this.SetPixels(colors, miplevel);
        }

        public void SetPixels(Color[] colors, int miplevel)
        {
            int blockWidth = this.width >> miplevel;
            if (blockWidth < 1)
            {
                blockWidth = 1;
            }
            int blockHeight = this.height >> miplevel;
            if (blockHeight < 1)
            {
                blockHeight = 1;
            }
            this.SetPixels(0, 0, blockWidth, blockHeight, colors, miplevel);
        }

        public void SetPixels(int x, int y, int blockWidth, int blockHeight, Color[] colors)
        {
            int miplevel = 0;
            this.SetPixels(x, y, blockWidth, blockHeight, colors, miplevel);
        }

        [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall]
        public extern void SetPixels(int x, int y, int blockWidth, int blockHeight, Color[] colors, int miplevel);
        public void SetPixels32(Color32[] colors)
        {
            int miplevel = 0;
            this.SetPixels32(colors, miplevel);
        }

        [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall]
        public extern void SetPixels32(Color32[] colors, int miplevel);

        public TextureFormat format { [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall] get; }

        public int mipmapCount { [MethodImpl(MethodImplOptions.InternalCall), WrapperlessIcall] get; }
    }
}

